/*------------------------------------------------------*/
/*                                                      */
/* Copyright (C)	sky-mobi.com                        */
/* All rights reserved                                  */
/*                                                      */
/* Author   tristan.yang                                */
/*                                                      */
/* History  2011-5-10 created                           */
/*                                                      */
/*------------------------------------------------------*/

#ifndef __PDU_BASE_H__
#define __PDU_BASE_H__

#include "RtBase.h"
#include "RtByteStream.h"
#include "RtMessageBlock.h"
#include "RtReferenceControl.h"

const WORD PDU_TYPE_BASE = 0;
//////////////////////////////////////////////////////////////////////////

class CPduBase : public CRtReferenceControlSingleThread
{
public:
	CPduBase()  {}
	virtual ~CPduBase() {}
	
public:
	virtual  RtResult Encode(CRtMessageBlock& mbBlock) const = 0;	
	virtual  RtResult Decode(CRtMessageBlock& mbBlock) = 0;
	virtual  DWORD GetLength() const  = 0;
};

template< typename PDU_TYPE_TYPE >
class CPduBaseEx : public CPduBase
{
public:
	typedef PDU_TYPE_TYPE Pdu_Type_Type;
	CPduBaseEx()
	{}
	
	CPduBaseEx(Pdu_Type_Type _Type)
		:m_Type(_Type)
	{}
	
	virtual ~CPduBaseEx()
	{}
	
	virtual RtResult Encode( CRtMessageBlock& mbBlock) const
	{
		CRtByteStreamIntel bsStream( mbBlock );
		bsStream << m_Type;
		return bsStream.IsGood() ? RT_OK : RT_ERROR_FAILURE;	
	}
	
	virtual RtResult Decode( CRtMessageBlock& mbBlock) 
	{
		CRtByteStreamIntel bsStream( mbBlock );
		bsStream >> m_Type;
		return bsStream.IsGood() ? RT_OK : RT_ERROR_FAILURE;	
	}
	
	virtual DWORD GetLength() const
	{
		return sizeof(m_Type);
	}
	
	Pdu_Type_Type GetType() const
	{
		return m_Type;
	}
	
	static RtResult PeekType(const CRtMessageBlock& mbBlock, Pdu_Type_Type& wType)
	{
		Pdu_Type_Type pBuf[1];
		RtResult ret = const_cast<CRtMessageBlock&>( mbBlock ).Read(
			pBuf, 
			sizeof(Pdu_Type_Type), 
			NULL, 
			FALSE );
		if (RT_SUCCEEDED(ret))
			wType = pBuf[0];
		return ret;	
	}
	
protected:	
	Pdu_Type_Type m_Type;
};

class CGcPduBase : public CPduBaseEx<WORD>
{
public:
	CGcPduBase(CPduBaseEx<WORD>::Pdu_Type_Type PduType = PDU_TYPE_BASE) 
		: CPduBaseEx<WORD>(PduType) {}
	virtual ~CGcPduBase() {}
};

#endif //__PDU_BASE_H__


